<script setup lang="ts">
import type {
  BusinessUIAction,
  BusinessUIFile,
  BusinessUIQueryColumnType,
  BusinessUIQueryType,
  DicType,
  WorkflowDesignRow
} from '@/types/custom'
import { computed, defineAsyncComponent, reactive, ref, unref, watch } from 'vue'
import { approvalStatusList, getBusinessBind } from '@/utils/custom'
import { assign, clone } from 'xe-utils'
import {
  getLinkageParams,
  onComponentServerFetch,
  onFetchIns,
  onFetchUser,
  onInitApiData,
  setFormDefaultParams,
  type StateInterface
} from '@/views/components/form/libs'
import { Close, Delete, Filter, FolderAdd, Refresh, Search, Checked } from '@element-plus/icons-vue'
import { Session } from '@/utils/storage'
import { isObjectValueEqual } from '@/utils/arrayOperation'
import { ElMessage } from 'element-plus'
import { storeToRefs } from 'pinia'
import { useAppState } from '@/stores/appState'
import emitter from '@/utils/mitt'

const TemplateQueryForm = defineAsyncComponent(
  () => import('@/views/components/form/components/TemplateQueryForm.vue')
)

interface Props {
  dicQuery?: DicType[]
  wfDesign?: WorkflowDesignRow
  uiQuery?: BusinessUIQueryType
  uiActions?: BusinessUIAction[]
  can_edit_items?: string[]
  rightSpacing?: number
  labelPosition?: string
  preview?: boolean
  btnLoading?: boolean
  showActions?: string[]
}

interface FormParamsType {
  [key: string]: any

  files?: BusinessUIFile[]
}

const modelValue = defineModel<boolean | undefined>()

const props = withDefaults(defineProps<Props>(), {
  rightSpacing: 0
})

const emit = defineEmits(['action', 'fetch'])

// 表单
const formRef = ref()
// 筛选key
const filterKey = `${props.uiQuery?.id || 'test'}_filter`
// 表单数据
const formParams = ref<FormParamsType>({})
// 部门-用户
const userItems = ref<SelectOptionType[]>([])
// 流程图列表
const insItems = ref<SelectOptionType[]>([])
// 动态数据
const state = reactive<StateInterface>({})
// 显示筛选
const isFilterCollapse = ref(Session.get(filterKey) || false)
// 懒加载筛选（展开才加载筛选，加载后不在重复加载）
const loadForm = ref(props.preview || isFilterCollapse.value)
// 初始值
const objectEqual = ref<TypedAny>({})

const { mobile } = storeToRefs(useAppState())

// 是否筛选
const isFilter = computed(() => {
  return isObjectValueEqual(unref(formParams), unref(objectEqual))
})

// 全局按钮
const globalUIActions = computed(() => {
  return props.uiActions
    ?.filter((f) => (props.showActions ? props.showActions.includes(f.action) : true))
    .filter((f) => f.global)
})

// 默认参数
const default_value_parse = computed(() => {
  return props.uiQuery?.default_value_parse || {}
})

// 全部表单列
const uiQueryItems = computed(() => props.uiQuery?.items || [])

// 过滤后表单列
const formItems = computed(() => uiQueryItems.value.filter((f) => !isRadioButton(f)))

/**
 * 显示出来的组件
 */
const toolItems = computed(() => uiQueryItems.value.filter((f) => isRadioButton(f)))

/**
 * 是否是分组
 * @param f
 */
const isRadioButton = (f: BusinessUIQueryColumnType) => {
  return ['el-radio-button'].includes(f.component)
}

/**
 * 是否联动
 * @param form
 */
const onLinkageChange = (form: BusinessUIQueryColumnType) => {
  if (form.linkage) {
    const items = unref(uiQueryItems)
    const params = getLinkageParams(items, unref(formParams))
    const linkage = form.set_json_parse.linkage || []
    const list = items.filter((f) => linkage.includes(f.field))
    onComponentServerFetch(list, state, params, unref(formParams))
    onInitDefaultData(list)
  }
}

/**
 * 获取选择器下拉
 * @param form
 */
const getOptions = (form: BusinessUIQueryColumnType): SelectOptionType[] => {
  if (form.component === 'sys-ins') {
    return insItems.value
  } else if (form.component === 'sys-wf-status') {
    return approvalStatusList
  } else if (form.component === 'sys-user') {
    return userItems.value
  } else if (
    ['el-select', 'el-checkbox-group', 'el-radio-group', 'el-radio-button'].includes(form.component)
  ) {
    return getDicOptions(form)
  } else if (form.options) {
    return form.options
  } else if (['api-select', 'api-tree-select'].includes(form.component)) {
    return state[form.field] || []
  } else {
    return state[form.component] || []
  }
}

/**
 * 获取字典下拉
 * @param form
 */
const getDicOptions = (form: BusinessUIQueryColumnType) => {
  const list: SelectOptionType[] = []
  props.dicQuery
    ?.filter((f) => f.column_name === form.field)
    .forEach((v) => {
      list.push({
        value: v.value_text,
        label: v.display_text
      })
    })
  return list
}

/**
 * 表单默认下拉
 * @param list
 */
const onInitDefaultData = (list: BusinessUIQueryColumnType[]) => {
  const params = getLinkageParams(unref(uiQueryItems), unref(formParams))
  if (list.some((s) => ['sys-user'].includes(s.component))) {
    onFetchUser(list, params).then((data) => {
      userItems.value = data
    })
  }
  if (list.some((s) => ['sys-ins'].includes(s.component))) {
    onFetchIns(list, params).then((data) => {
      insItems.value = data
    })
  }
  onComponentServerFetch(list, state, params, unref(formParams))
  onInitApiData(list, state, params, unref(formParams))
}

/**
 * 每次查询栏配置变化进行初始化
 */
const initDefaultData = (uiQuery?: BusinessUIQueryType) => {
  if (!uiQuery) return onFetch()
  onResetParams()
  onInitDefaultData(unref(uiQueryItems))
  onFetch()
}

const onFilterCollapse = () => {
  isFilterCollapse.value = !isFilterCollapse.value
  if (isFilterCollapse.value) loadForm.value = isFilterCollapse.value
}

/**
 * 操作
 * @param action
 */
const onAction = (action: BusinessUIAction) => {
  emit('action', action)
}

/**
 * 查询
 */
const onFetch = () => {
  const params = unref(formParams)
  const vm = unref(formRef)
  if (vm) {
    vm.validate((valid: boolean) => {
      if (valid) {
        emit('fetch', params)
      } else {
        ElMessage.warning('查询参数验证失败。')
      }
    })
  } else {
    emit('fetch', params)
  }
  if (mobile.value) isFilterCollapse.value = false
}

/**
 * 重置
 */
const onResetParams = () => {
  const params = assign(setFormDefaultParams(unref(uiQueryItems), {}), unref(default_value_parse))
  objectEqual.value = clone(params, true)
  formParams.value = params
}

const openWorkflow = () => {
  if (props.wfDesign?.id) emitter.emit('onOpenWorkflow', props.wfDesign)
}

const textLength = computed(() => {
  const actions = unref(globalUIActions) || []
  return actions.map((v) => v.name.length).reduce((acc, v) => acc + v)
})

watch(isFilterCollapse, (value) => {
  Session.set(filterKey, value)
})

watch(() => props.uiQuery, initDefaultData, { immediate: true })
</script>

<template>
  <div class="template-query w100 pa5">
    <el-space :size="[5, 5]" class="flex flex-warp">
      <el-button
        :icon="Filter"
        circle
        :class="{ 'border-danger color-danger': !isFilter }"
        @click="onFilterCollapse"
      />
      <slot name="query_tool">
        <el-radio-group
          class="ml0 flex-shrink"
          v-for="(form, index) in toolItems"
          :key="index"
          v-model="formParams[form.field]"
          v-bind="getBusinessBind(form)"
          @change="onFetch"
        >
          <el-radio-button
            v-for="item in getOptions(form)"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-radio-group>
        <slot name="query_default"></slot>
        <el-button
          v-for="(action, index) in globalUIActions"
          :key="index"
          :type="action.type"
          :icon="{ Add: FolderAdd, TableSelector: Checked }[action.action]"
          @click="onAction(action)"
          plain
          :disabled="btnLoading"
          class="ml0"
        >
          {{ action.name }}
        </el-button>
      </slot>
      <el-button
        v-if="!mobile && isFilterCollapse"
        :icon="Search"
        type="primary"
        :loading="modelValue"
        @click="onFetch"
        class="ml0"
      >
        查询
      </el-button>
      <el-button v-else :icon="Refresh" :loading="modelValue" @click="onFetch" class="ml0">
        刷新
      </el-button>
      <div v-if="mobile" style="height: 24px;width: 50px;"></div>
    </el-space>
    <el-drawer
      v-if="mobile"
      v-model="isFilterCollapse"
      title="筛选"
      direction="rtl"
      size="80%"
      append-to-body
    >
      <TemplateQueryForm
        v-if="loadForm"
        ref="formRef"
        v-model="formParams"
        :items="formItems"
        label-position="left"
        @linkage="onLinkageChange"
        @fetch="onFetch"
        :get-options="getOptions"
        class="ml10 mr10"
      />
      <div class="flex align-center justify-around mt20">
        <el-button
          :icon="Close"
          :loading="modelValue"
          @click="isFilterCollapse = false"
          class="ml5"
        >
          关闭
        </el-button>
        <el-button
          :disabled="isFilter"
          :icon="Delete"
          circle
          :loading="modelValue"
          @click="onResetParams"
        />
        <el-button type="primary" :icon="Search" :loading="modelValue" @click="onFetch" class="ml5">
          筛选
        </el-button>
      </div>
    </el-drawer>
    <TemplateQueryForm
      v-else-if="loadForm"
      ref="formRef"
      v-show="isFilterCollapse || preview"
      v-model="formParams"
      :items="formItems"
      :label-position="labelPosition"
      @linkage="onLinkageChange"
      @fetch="onFetch"
      :get-options="getOptions"
    />
    <div
      v-if="!mobile"
      :class="mobile ? (textLength > 10 ? 'operate-mobile' : 'operate-pc') : 'operate-pc'"
      :style="{ paddingRight: `${rightSpacing}px` }"
    >
      <span
        v-if="wfDesign"
        class="color-primary cursor-pointer cursor-pointer-line"
        @click="openWorkflow"
      >
        流程：{{ wfDesign.name }}
      </span>
      <el-button
        v-if="isFilterCollapse"
        title="重置"
        :disabled="isFilter"
        :icon="Delete"
        circle
        :loading="modelValue"
        @click="onResetParams"
        class="ml5"
      />
    </div>
  </div>
</template>

<style lang="scss">
.template-query {
  background-color: var(--el-bg-color);
  border-radius: 8px 8px 0 0;

  .operate-pc {
    position: absolute;
    right: 5px;
    top: 5px;
    display: flex;
    align-items: center;
    z-index: 1;
    height: 24px;
  }

  .operate-mobile {
    text-align: right;
    margin-top: 5px;
    margin-bottom: 5px;
  }

  .el-form-item--small {
    .el-form-item__label {
      height: 22px;
      line-height: 22px;
    }
  }

  // .el-form-item__label-wrap {
  //   background-color: var(--el-fill-color-light);
  //   color: var(--el-color-info);
  //   position: relative;
  //   display: inline-flex;
  //   align-items: center;
  //   justify-content: center;
  //   min-height: 100%;
  //   border-radius: var(--el-input-border-radius);
  //   padding: 0 10px;
  //   white-space: nowrap;
  //   border: 1px solid var(--el-border-color);
  //   margin-left: 0 !important;

  //   .el-form-item__label {
  //     padding-right: 0 !important;
  //   }
  // }

  // .el-form-item__content {
  //   .el-textarea__inner,
  //   .el-select__wrapper,
  //   .el-input__wrapper {
  //     border-radius: 0 !important;
  //   }
  //   .el-select,
  //   .el-textarea,
  //   .el-input {
  //     transform: translateX(-1px);
  //   }
  // }
}
</style>
